package tracing;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import wdmsim.Constants;
import wdmsim.Simulator;
import events.Event;
import events.OBGPDestroyLightpathEvent;
import events.OBGPIntradomainUpdateEvent;
import events.OBGPUpdateEvent;
import events.RouteRequestEvent;

public class OBGPTracer extends Trace {

	/**
	 * Singleton object to implement a static class
	 * This is useful when exactly one object is needed to coordinate actions across the system
	 */
	protected static OBGPTracer singletonObject;
	private PrintWriter trace;
	//private int intradomainLightpath;
	Statistic statistic;
	
	public OBGPTracer() throws IOException {
		cleanVariables();
		statistic = Statistic.getStatisticObject();
		setTraceFile(Simulator.TRACER_NAME);
	}
	
	public static synchronized OBGPTracer getTracerObject() throws IOException {
    	if (singletonObject == null) 
    		singletonObject = new OBGPTracer();
    	return(singletonObject);
    }
	
	public void setTraceFile(String filename) throws IOException {
        trace = new PrintWriter(new BufferedWriter(new FileWriter(filename)), true);
        //trace.println("*****************  TRACER SIMULATOR  ***********************");
    }

	public void addEvent(Event event) {		
		if(event instanceof RouteRequestEvent) {
			if(!((RouteRequestEvent) event).getFlow().getPath().getLightpaths().isEmpty()) {
				trace.println("rq " + event.toString() + " " + ((RouteRequestEvent) event).getFlow().getPath().getLightpaths().get(0).getWavelength());
			} else {
				trace.println("rq " + event.toString());
			}
			
		} else if(event instanceof OBGPDestroyLightpathEvent) {
			trace.println("ld " + event.toString());
			
		} else if(event instanceof OBGPUpdateEvent) {
			trace.println("up " + event.toString());
			
		} else if(event instanceof OBGPIntradomainUpdateEvent) {
			trace.println("up " + event.toString());
			
		} 
	}
	
	public void showAllResults(long begin) {
		// print simulation 
		trace.println("\nSIMULATION TIME = " + (Simulator.SIMULATION_TOTAL_TIME/1000000) + "s");
		trace.println("\nCLOCK TIME = " + ((System.currentTimeMillis() - begin) / 1000) + " sec");
		trace.println("\nNUMBER OF CALLS: " + (statistic.getInsertedFlows()+statistic.getAccepts()+statistic.getBlocks()));
		trace.println("\nACCEPTED CALLS: " + (statistic.getAccepts()));
		trace.println("\nBLOCKED CALLS: " + statistic.getBlocks());
		trace.println("\nINSERTED FLOWS: "+ statistic.getInsertedFlows());
		trace.println("\nUPDATE MESSAGES: "+ statistic.getUpdateMessages());
		double meanSetupTime = (statistic.getSetupTime()/statistic.getAccepts());
		trace.println("\nMEAN SETUP TIME: " + (meanSetupTime/Constants.SECOND) + "s");
	}

	/**
	 * 
	 */
	public void reportBlockedCall(Event event) {
		trace.println("bl " + event.toString());	
		statistic.blockedCall();
	}

	/**
	 * 
	 * @param event
	 */
	public void reportLightpathCreated(RouteRequestEvent event) {
		trace.println("lc " + event.toString() + " " +  event.getFlow().getPath().getLightpaths().get(0).getWavelength());	
		statistic.lightpathCreated(event);
	}
	
	/**
	 * 
	 */
	public void reportIntradomainLightpathCreated(Event event) {
		trace.println("lp " + event.toString());
		statistic.lightpathCreated((RouteRequestEvent)event);
	}

	/**
	 * @param event
	 */
	public void reportCrankBackEvent(RouteRequestEvent event) {
		trace.println("cb " + event.toString());
		statistic.addCranks(event);
	}

	public void traceSetup(int numNodes, int i, int j) {
		// TODO Auto-generated method stub
		
	}
	
	public void cleanVariables() {
    	
    }

	/**
	 * 
	 */
	public void reportUpdateMessage() {
		
		statistic.updateMessage();
	}

	/**
	 * @param event
	 */
	public void reportFlowInserting(RouteRequestEvent event) {
		trace.println("fi " + event.toString() + " " +  event.getFlow().getPath().getLightpaths().get(0).getWavelength());
		statistic.flowInserting(event);
	}

}
